import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import csv
import os
from DataSheetClass import Sheet,DataSheet
from DataInterfaceClass import DataInterface
from datetime import datetime
import shutil

class CsvDatas(DataInterface):
    def __init__(self, datasheet:DataSheet):
        super().__init__(datasheet=datasheet)
        
    def read_source(self):
        self.datasheet.clearSheets()
        self.datasheet.append_sheet(Sheet("csv_only_sheet"))
        self.datasheet.set_current_sheet_by_index(0)
        
        try:
            with open(self.datasheet.source_file_path, mode='r', newline='', encoding='utf-8') as file:
                reader = csv.reader(file)
                for row in reader:
                    self.datasheet.current_sheet.rows.append(row)
            
            # 如果data_sheet的name未设置，则设置为不包含后缀的filename
            if not self.datasheet.current_sheet.name:
                self.datasheet.current_sheet.name = os.path.splitext(os.path.basename(self.datasheet.source_file_path))[0]
        except FileNotFoundError:
            raise ValueError(f"File {self.datasheet.source_file_path} not found")
        except Exception as e:
            raise ValueError(f"Failed to read file: {e}")

    def update_source(self):
        if not self.datasheet.source_file_path:
            raise ValueError("No CSV filename provided, cannot save")
        
        try:
            filepath = self.datasheet.source_file_path
            
            # backup
            filename,fileext = os.path.splitext(filepath)
            current_time_str = datetime.now().strftime('%Y%m%d_%H%M%S')
            backup_filepath = f"{filename}_backup_{current_time_str}{fileext}"
            try:
                shutil.copy(filepath, backup_filepath)
            except IOError as e:
                print(f"Unable to copy file. {e}")
            except Exception as ex:
                print(f"Unexpected error: {ex}")

            # update file
            with open(filepath, mode='w', newline='', encoding='utf-8') as file:
                writer = csv.writer(file)                
                for row in self.datasheet.current_sheet.rows:
                    writer.writerow(row)
        except Exception as e:
            raise ValueError(f"Failed to save file: {filepath}->{e}")
            
            
    def view(self):
        self.root = tk.Tk()        
        
        # 设置窗口标题为文件名或默认标题
        self.set_window_title()

        # 创建一个树形视图控件
        self.tree = ttk.Treeview(self.root, show='headings')
        self.tree.pack(expand=True, fill=tk.BOTH)

        # 设置双击事件以进入编辑模式
        self.tree.bind('<Double-1>', self.on_double_click)
        self.tree.heading('#0', command=lambda: None)  # 禁用根heading的点击事件

        # 当前正在编辑的项
        self.current_item = None
        self.entry_var = tk.StringVar()
        self.entry = tk.Entry(self.root, textvariable=self.entry_var)
        self.entry.bind('<Return>', self.on_edit_done)
        self.entry.bind('<FocusOut>', self.on_edit_done)

        # 添加按钮框架
        button_frame = tk.Frame(self.root)
        button_frame.pack(side=tk.TOP, fill=tk.X)

        # 添加AddRow按钮
        self.add_row_button = tk.Button(button_frame, text="AddRow", command=self.on_add_row)
        self.add_row_button.pack(side=tk.LEFT, padx=5)

        # 添加RemoveRow按钮
        self.remove_row_button = tk.Button(button_frame, text="RemoveRow", command=self.on_remove_row)
        self.remove_row_button.pack(side=tk.LEFT, padx=5)

        # 添加AddCol按钮
        self.add_col_button = tk.Button(button_frame, text="AddCol", command=self.on_add_col_dialog)
        self.add_col_button.pack(side=tk.LEFT, padx=5)

        # 添加RemoveCol按钮
        self.remove_col_button = tk.Button(button_frame, text="RemoveCol", command=self.on_remove_col_dialog)
        self.remove_col_button.pack(side=tk.LEFT, padx=5)

        # 添加RenameHeader按钮
        self.rename_header_button = tk.Button(button_frame, text="RenameHeader", command=self.on_rename_header_dialog)
        self.rename_header_button.pack(side=tk.LEFT, padx=5)

        # 添加保存按钮
        self.save_button = tk.Button(button_frame, text="Save", command=self.update_source)
        self.save_button.pack(side=tk.RIGHT, padx=5)    
        
        self.preview()
        
        self.root.mainloop()
    def preview(self):
        # 清空现有数据
        for i in self.tree.get_children():
            self.tree.delete(i)
        
        if not self.datasheet.current_sheet.rows:
            raise ValueError("Data is empty. Cannot preview.")
            return
        
        # 提取表头
        self.headers = self.datasheet.current_sheet.rows[0]
        
        # 设置列
        self.tree.config(columns=self.headers, show='headings')
        for header in self.headers:
            self.tree.heading(header, text=header, command=lambda h=header: self.edit_header(h))
        
        # 插入新数据
        for row in self.datasheet.current_sheet.rows[1:]:  # 跳过表头
            self.tree.insert("", "end", values=row)

    def set_window_title(self):
        if self.datasheet.current_sheet.name:
            self.root.title(f"{self.datasheet.current_sheet.name} - Tkinter CSV Editor")
        else:
            self.root.title("Tkinter CSV Editor")

    def on_double_click(self, event):
        # 获取当前点击的列和行
        region = self.tree.identify_region(event.x, event.y)
        if region == "cell":
            rowid = self.tree.identify_row(event.y)
            column = self.tree.identify_column(event.x)
            col_index = int(column.replace('#', '')) - 1
            
            x, y, width, height = self.tree.bbox(rowid, column)
            
            # 获取当前单元格的值
            value = self.tree.item(rowid)['values'][col_index]

            # 显示输入框并设置其位置和大小
            self.entry.place(x=x, y=y, width=width, height=height)
            self.entry_var.set(value)
            self.entry.focus_set()

            # 记录当前编辑的项
            self.current_item = (rowid, col_index)

    def edit_header(self, header):
        # 获取所有列的索引
        headers = self.tree["columns"]
        col_index = headers.index(header)
        
        # 获取当前列的位置
        bbox = self.tree.bbox('', column=f'#{col_index + 1}')
        if not bbox:
            return
        
        x, y, width, height = bbox
        
        # 显示输入框并设置其位置和大小
        self.entry.place(x=x, y=y, width=width, height=height)
        self.entry_var.set(header)
        self.entry.focus_set()

        # 记录当前编辑的列
        self.current_item = ('#0', col_index)

    def on_edit_done(self, event=None):
        if self.current_item:
            item_id, col_index = self.current_item
            new_value = self.entry_var.get()
            
            if item_id == '#0':  # 编辑的是表头
                # 更新表头
                old_header = self.headers[col_index]
                self.headers[col_index] = new_value
                
                # 更新Treeview的表头
                self.tree.heading(old_header, text=new_value)
                
                # 更新所有行的数据
                for i, row in enumerate(self.datasheet.current_sheet.rows):
                    row[col_index] = new_value if i == 0 else row[col_index]
            else:  # 编辑的是单元格
                index = self.tree.index(item_id) + 1  # 因为我们跳过了表头
                self.datasheet.current_sheet.rows[index][col_index] = new_value
                
                # 更新tree view
                old_values = list(self.tree.item(item_id)['values'])
                old_values[col_index] = new_value
                self.tree.item(item_id, values=old_values)
            
            # 移除输入框
            self.entry.place_forget()
            self.current_item = None

    def on_add_row(self):
        if not self.headers:
            messagebox.showwarning("Warning", "Please add columns first before adding rows.")
            return
        
        if len(self.datasheet.current_sheet.rows) == 1:
            # 如果只有表头，直接在最后插入新行
            new_row = [''] * len(self.headers)
            self.datasheet.current_sheet.rows.append(new_row)
        else:
            selected_items = self.tree.selection()
            if not selected_items:
                messagebox.showwarning("Warning", "Please select a row to add a new row below.")
                return
            
            selected_item = selected_items[0]
            index = self.tree.index(selected_item)
            
            # 在选中行下方插入新行
            new_row = [''] * len(self.headers)
            self.datasheet.current_sheet.rows.insert(index + 1 + 1, new_row)  # +1是因为跳过了表头
        
        # 更新Treeview
        self.preview()

    def on_remove_row(self):
        if not self.headers:
            messagebox.showwarning("Warning", "Please add columns first before removing rows.")
            return
        
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showwarning("Warning", "Please select a row to remove.")
            return
        
        selected_item = selected_items[0]
        index = self.tree.index(selected_item)
        
        # 检查是否是除表头外的最后一行
        if len(self.datasheet.current_sheet.rows) == 2 and index == 0:
            messagebox.showwarning("Warning", "Cannot remove the last row.")
            return
        
        # 删除数据源中的行
        del self.datasheet.current_sheet.rows[index + 1]  # +1是因为跳过了表头
        
        # 更新Treeview
        self.preview()

    def on_add_col_dialog(self):
        dialog = tk.Toplevel(self.root)
        dialog.title("Add Column")

        # 输入列位置
        pos_label = tk.Label(dialog, text="Insert Position (1 to {}):".format(len(self.headers) + 1))
        pos_label.grid(row=0, column=0, padx=5, pady=5)
        pos_entry = tk.Entry(dialog)
        pos_entry.grid(row=0, column=1, padx=5, pady=5)

        # 输入列名称
        name_label = tk.Label(dialog, text="Column Name:")
        name_label.grid(row=1, column=0, padx=5, pady=5)
        name_entry = tk.Entry(dialog)
        name_entry.grid(row=1, column=1, padx=5, pady=5)

        def on_confirm():
            try:
                position = int(pos_entry.get())
                if position < 1 or position > len(self.headers) + 1:
                    raise ValueError("Invalid position")
                name = name_entry.get().strip()
                if not name:
                    raise ValueError("Column name cannot be empty")
                self.on_add_col(position, name)
                dialog.destroy()
            except ValueError as e:
                raise ValueError(str(e))

        confirm_button = tk.Button(dialog, text="Confirm", command=on_confirm)
        confirm_button.grid(row=2, columnspan=2, pady=10)

    def on_add_col(self, position, name):
        print(f"Adding column '{name}' at position {position}")
        
        # 在指定位置插入新列
        for row in self.datasheet.current_sheet.rows:
            row.insert(position - 1, '')
        
        self.datasheet.current_sheet.rows[0][position - 1] = name
        
        # 更新表头
        self.headers = self.datasheet.current_sheet.rows[0]
        
        # 打印每一行的数据以调试
        for idx, row in enumerate(self.datasheet.current_sheet.rows):
            print(f"Row {idx}: {row}")
        
        # 更新Treeview
        self.preview()

    def on_remove_col_dialog(self):
        if not self.headers:
            messagebox.showwarning("Warning", "Please add columns first before removing columns.")
            return
        
        dialog = tk.Toplevel(self.root)
        dialog.title("Remove Column")

        # 下拉框选择列
        col_label = tk.Label(dialog, text="Select Column to Remove:")
        col_label.grid(row=0, column=0, padx=5, pady=5)
        col_var = tk.StringVar()
        col_combobox = ttk.Combobox(dialog, textvariable=col_var, values=self.headers[:-1])  # 不允许删除最后一列
        col_combobox.grid(row=0, column=1, padx=5, pady=5)

        def on_confirm():
            selected_column = col_var.get()
            if not selected_column:
                raise ValueError("Please select a column")
                return
            self.on_remove_col(selected_column)
            dialog.destroy()

        confirm_button = tk.Button(dialog, text="Confirm", command=on_confirm)
        confirm_button.grid(row=1, columnspan=2, pady=10)

    def on_remove_col(self, column_name):
        # 删除数据源中的列
        if column_name in self.headers:
            col_index = self.headers.index(column_name)
            del self.headers[col_index]
            for row in self.datasheet.current_sheet.rows:
                if len(row) > col_index:  # Ensure the row has enough columns
                    del row[col_index]
        
            # 更新Treeview
            self.preview()
        else:
            raise ValueError("Column not found")

    def on_rename_header_dialog(self):
        if not self.headers:
            messagebox.showwarning("Warning", "Please add columns first before renaming headers.")
            return
        
        dialog = tk.Toplevel(self.root)
        dialog.title("Rename Header")

        # 下拉框选择列
        col_label = tk.Label(dialog, text="Select Column to Rename:")
        col_label.grid(row=0, column=0, padx=5, pady=5)
        col_var = tk.StringVar()
        col_combobox = ttk.Combobox(dialog, textvariable=col_var, values=self.headers)
        col_combobox.grid(row=0, column=1, padx=5, pady=5)

        # 输入新列名称
        new_name_label = tk.Label(dialog, text="New Column Name:")
        new_name_label.grid(row=1, column=0, padx=5, pady=5)
        new_name_entry = tk.Entry(dialog)
        new_name_entry.grid(row=1, column=1, padx=5, pady=5)

        def on_confirm():
            selected_column = col_var.get()
            new_name = new_name_entry.get().strip()
            if not selected_column:
                raise ValueError("Please select a column")
                return
            if not new_name:
                raise ValueError("New column name cannot be empty")
                return
            self.on_rename_header(selected_column, new_name)
            dialog.destroy()

        confirm_button = tk.Button(dialog, text="Confirm", command=on_confirm)
        confirm_button.grid(row=2, columnspan=2, pady=10)

    def on_rename_header(self, old_name, new_name):
        # 修改数据源中的列名称
        if old_name in self.headers:
            col_index = self.headers.index(old_name)
            self.headers[col_index] = new_name
            
            # 更新所有行的数据（第一行是表头）
            for row in self.datasheet.current_sheet.rows:
                row[col_index] = new_name if row is self.headers else row[col_index]
        
            # 更新Treeview
            self.preview()
        else:
            raise ValueError("Column not found")

if __name__ == "__main__":
    app = CsvDatas(filename="qfn4x4_bondingtable.csv")  # 替换为你的CSV文件名
    app.view()  # 手动调用preview方法



